// $Id: Cli.cpp 128 2007-11-17 15:49:11Z bram $


/**
 * Commandline interface definition file.
 *
 * @file Cli.cpp
 * @author Bram Bonn&eacute;
 */

#include "Cli.h"


//----------------------------------------------------------------------------
// Constructor.

/**
 * Start het spel, en laat de spelers zetten uitvoeren.
 */
Cli::Cli(void) {
	ReadPlayerNames();
	m_game = new Game(m_p1Name, m_p2Name);

	while (m_game->BothMovePossible()) {
		PrintBoard();
		if (m_game->ValidMovePossible(BLACK))
			AskNewMove(BLACK);
		PrintBoard();
		if (m_game->ValidMovePossible(WHITE))
			AskNewMove(WHITE);
	}

	EndGame();
}

Cli::~Cli(void) {
	delete m_game;
	PlayerDB database;//Omwille van nu reeds geüpdate database.
	cout << "\n\nHighscores:\n" << database.GetHighScores();
}

//----------------------------------------------------------------------------
// Private methods.

/**
 * Beëindig het spel, en schrijf de score (en de winnaar) uit.
 */

void Cli::EndGame() const {
	int blackNum = m_game->CountPieces(BLACK), whiteNum = m_game->CountPieces(WHITE);

	PrintBoard();
	cout << "\nHet spel is afgelopen, er kunnen geen mogelijke zetten meer gedaan worden.\n\n";
	if (blackNum > whiteNum)
		cout << m_p1Name << " (zwart) heeft gewonnen.";
	else if (whiteNum > blackNum)
		cout << m_p2Name << " (wit) heeft gewonnen.";
	else
		cout << "Gelijkspel!";
	cout << "\n\nDe eindstand is: \n" << m_p1Name << " (zwart): " << blackNum;
	cout << "\n" << m_p2Name << " (wit): " << whiteNum;
}

/**
 * Lees spelernamen in.
 *
 * @param [in] player1
 * 	De eerste speler.
 * @param [in] player2
 * 	De tweede speler.
 */

void Cli::ReadPlayerNames() {
	cout << "Geef naam voor de speler met kleur zwart: ";
	cin >> m_p1Name;
	cout << "Geef naam voor de speler met kleur wit: ";
	cin >> m_p2Name;
}


/**
 * Laat de speler een zet uitvoeren.
 *
 * @param [in] speler
 * 	De speler die een zet mag uitvoeren.
 */

void Cli::AskNewMove(Piece speler) const {
	bool moveSet = false;
	int x, y;
	string playerName = (speler == WHITE) ? m_p2Name : m_p1Name;

	cout << playerName << " (" << PieceToChar(speler) << ") , geef x <spatie> y: ";
	cin >> x >> y;
	moveSet = m_game->TryPieceMove(speler, x, y);
	while (!moveSet) { //Blijf opnieuw proberen zolang de zet niet geldig is
		cout << "Zet niet mogelijk op deze plaats, probeer opnieuw: ";
		cin >> x >> y;
		moveSet = m_game->TryPieceMove(speler, x, y);
	}
}


/**
 * Schrijft het spelbord uit.
 */

void Cli::PrintBoard() const {
	Board board = m_game->GetBoard();
	int x, y;

	system("clear");
	cout << "  "; //Voor het printen van de kolommen
	for (x = 0; x < board.GetSize(); x ++)
		cout << x << ' ';
	cout << endl;

	for (y = 0; y < board.GetSize(); y ++) {
		cout << y << ' '; //Print het nummer van de rij
		for (x = 0; x < board.GetSize(); x ++)
			cout << PieceToChar(board.GetPiece(x, y)) << ' ';
		cout << endl;
	}
}


/**
 * Zet een 'piece' om naar zijn visuele voorstelling in de terminal.
 * De letters 'Z' en 'W' kunnen aangepast worden voor een andere representatie.
 */

char Cli::PieceToChar(Piece piece) const {
	if (piece == EMPTY)
		return '.';
	else if (piece == BLACK)
		return 'Z';
	else if (piece == WHITE)
		return 'W';
	else {
		InternalException e("Cli::PieceToChar", "Piece heeft geen waarde");
		throw(e);
	}
}
